package ac.il.technion.c236369.hw4.core.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import ac.il.technion.c236369.hw4.typehandlers.TypeHandler;


/**
 * @author Artem Barger, MAxim Aizenshtein
 * 
 * Look up for class only by it short name
 * starting in current directory, after it
 * finds class load it into memory.
 *
 */
public class FindClassFileByNameLoader extends ClassLoader {

	public static String findFile( File root, String fileName) {
		File[] list = root.listFiles();
		List<File> folders = new ArrayList<File>( );
		for( File $ : list) {
			if ( $.isDirectory( )) {
				folders.add($);
			}
			if ($.getName().equals(fileName))
				return $.getAbsolutePath( );
		}
		for ( File $ : folders) {
			String path = findFile( $, fileName);
			if ( path == null)
				continue;
			return path;
		}
		return null;
	}
	
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] classBytes = null;
		try {
			classBytes = loadClassBytes(name);
		} catch (IOException e) {
			throw new ClassNotFoundException(name);
		}

		Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
		if (cl == null)
			throw new ClassNotFoundException(name);
		return cl;
	}

	/**
	 * @param name
	 *            the class name
	 * @return an array with the class file bytes
	 */
	private byte[] loadClassBytes(String name) throws IOException {
		String cname = findFile( new File( "."), name + ".class");
		FileInputStream in = null;
		in = new FileInputStream(cname);
		try {
			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
			int ch;
			while ((ch = in.read()) != -1) {
				byte b = (byte) (ch);
				buffer.write(b);
			}
			in.close();
			return buffer.toByteArray();
		} finally {
			in.close();
		}
	}

	public static void main(String[] args) {
		FindClassFileByNameLoader loader = new FindClassFileByNameLoader( );
		try {
			TypeHandler handler = (TypeHandler)loader.loadClass( "TSPEngine").newInstance();
			if ( handler != null)
			{
				System.out.println( "Loaded");
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
}
